//@ts-nocheck
// Modify n value to change the difficulty of the benchmark
// suggesting using input = 5500;

const input: number = 5500;

declare interface ArkTools {
	timeInUs(arg:any):number
}

function approximate(n: number): number {
    const u: number[] = Array(n).fill(1.0);
    const v: number[] = Array(n).fill(0.0);

    for (let count = 0; count < 10; count++) {
        multiplyAtAv(n, u, v);
        multiplyAtAv(n, v, u);
    }

    let vBv = 0.0, vv = 0.0;
    for (let i = 0; i < n; i++) {
        vBv += u[i] * v[i];
        vv += v[i] * v[i];
    }

    return Math.sqrt(vBv / vv);
}

function a(i: number, j: number): number {
    const ij = i + j;
    return 1.0 / (ij * (ij + 1) / 2 + i + 1);
}

function multiplyAv(n: number, v: number[], av: number[]): void {
    for (let i = 0; i < n; i++) {
        av[i] = 0.0;
        for (let j = 0; j < n; j++) {
            av[i] += a(i, j) * v[j];
        }
    }
}

function multiplyAtv(n: number, v: number[], atv: number[]): void {
    for (let i = 0; i < n; i++) {
        atv[i] = 0;
        for (let j = 0; j < n; j++) {
            atv[i] += a(j, i) * v[j];
        }
    }
}

function multiplyAtAv(n: number, v: number[], atAv: number[]): void {
    const u: number[] = Array(n).fill(0.0);
    multiplyAv(n, v, u);
    multiplyAtv(n, u, atAv);
}

function runSpectralnorm():number{

    const n: number = input;
    const start = ArkTools.timeInUs();
    const result = approximate(n).toFixed(9);
    const end = ArkTools.timeInUs();
    let time = (end -start) / 1000
    print("Numerical Calculation - spectralnorm:\t"+String(time)+"\tms");
}
